#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统计计算模块 - 计算作业面积、距离等数据
"""
import math
from typing import List, Tuple

class StatsCalculator:
    """统计数据计算器"""
    
    @staticmethod
    def haversine_distance(lat1, lon1, lat2, lon2):
        """
        计算两个GPS坐标之间的距离（米）
        使用Haversine公式
        """
        R = 6371000  # 地球半径（米）
        
        phi1 = math.radians(lat1)
        phi2 = math.radians(lat2)
        delta_phi = math.radians(lat2 - lat1)
        delta_lambda = math.radians(lon2 - lon1)
        
        a = math.sin(delta_phi / 2) ** 2 + \
            math.cos(phi1) * math.cos(phi2) * \
            math.sin(delta_lambda / 2) ** 2
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
        
        distance = R * c
        return distance
    
    @staticmethod
    def calculate_distance(gps_points):
        """
        计算GPS轨迹的总距离（米）
        gps_points: [(lat, lon), (lat, lon), ...]
        """
        if len(gps_points) < 2:
            return 0.0
        
        total_distance = 0.0
        for i in range(1, len(gps_points)):
            lat1, lon1 = gps_points[i-1]
            lat2, lon2 = gps_points[i]
            total_distance += StatsCalculator.haversine_distance(lat1, lon1, lat2, lon2)
        
        return total_distance
    
    @staticmethod
    def calculate_polygon_area(boundary_points):
        """
        计算多边形面积（平方米）
        使用Shoelace公式
        boundary_points: [(lat, lon), (lat, lon), ...]
        """
        if len(boundary_points) < 3:
            return 0.0
        
        # 转换经纬度到米制坐标（近似）
        # 在小范围内，1度纬度约111km，1度经度约111km*cos(纬度)
        avg_lat = sum(p[0] for p in boundary_points) / len(boundary_points)
        
        lat_to_m = 111000  # 1度纬度约111km
        lon_to_m = 111000 * math.cos(math.radians(avg_lat))  # 1度经度
        
        # 转换为米制坐标
        points_m = [
            (lat * lat_to_m, lon * lon_to_m)
            for lat, lon in boundary_points
        ]
        
        # Shoelace公式计算面积
        area = 0.0
        n = len(points_m)
        for i in range(n):
            j = (i + 1) % n
            area += points_m[i][0] * points_m[j][1]
            area -= points_m[j][0] * points_m[i][1]
        area = abs(area) / 2.0
        
        return area
    
    @staticmethod
    def calculate_work_area(gps_track, work_width=2.0):
        """
        基于GPS轨迹计算作业面积（平方米）
        gps_track: [(lat, lon), (lat, lon), ...]
        work_width: 作业宽度（米）
        """
        if len(gps_track) < 2:
            return 0.0
        
        # 简单方法：距离 * 作业宽度
        distance = StatsCalculator.calculate_distance(gps_track)
        area = distance * work_width
        
        return area
    
    @staticmethod
    def calculate_work_area_advanced(gps_track, work_width=2.0):
        """
        高级方法：考虑重叠区域
        将轨迹分段，计算每段的作业条带，去除重叠
        """
        if len(gps_track) < 2:
            return 0.0
        
        # TODO: 实现更精确的面积计算算法
        # 目前使用简单方法
        return StatsCalculator.calculate_work_area(gps_track, work_width)
    
    @staticmethod
    def meters_to_mu(area_m2):
        """
        将平方米转换为亩
        1亩 = 666.67平方米
        """
        return area_m2 / 666.67
    
    @staticmethod
    def calculate_field_coverage(gps_track, field_boundary, work_width=2.0):
        """
        计算地块覆盖率
        gps_track: GPS轨迹点
        field_boundary: 地块边界点
        work_width: 作业宽度
        """
        work_area = StatsCalculator.calculate_work_area(gps_track, work_width)
        field_area = StatsCalculator.calculate_polygon_area(field_boundary)
        
        if field_area == 0:
            return 0.0
        
        coverage = min((work_area / field_area) * 100, 100.0)
        return coverage
    
    @staticmethod
    def calculate_fuel_consumption(distance_m, speed_kmh=5.0, base_rate=3.5):
        """
        估算燃油消耗（升）
        distance_m: 行驶距离（米）
        speed_kmh: 平均速度（km/h）
        base_rate: 基础油耗（升/小时）
        """
        distance_km = distance_m / 1000.0
        time_hours = distance_km / speed_kmh if speed_kmh > 0 else 0
        fuel = time_hours * base_rate
        return fuel
    
    @staticmethod
    def calculate_efficiency(area_m2, duration_seconds):
        """
        计算作业效率（亩/小时）
        """
        if duration_seconds == 0:
            return 0.0
        
        area_mu = StatsCalculator.meters_to_mu(area_m2)
        duration_hours = duration_seconds / 3600.0
        efficiency = area_mu / duration_hours if duration_hours > 0 else 0
        
        return efficiency
    
    @staticmethod
    def analyze_work_session(gps_track, field_boundary=None, work_width=2.0, 
                            duration_seconds=0, avg_speed=5.0):
        """
        综合分析一次作业会话
        返回完整的统计数据
        """
        distance_m = StatsCalculator.calculate_distance(gps_track)
        distance_km = distance_m / 1000.0
        
        work_area_m2 = StatsCalculator.calculate_work_area(gps_track, work_width)
        work_area_mu = StatsCalculator.meters_to_mu(work_area_m2)
        
        fuel_l = StatsCalculator.calculate_fuel_consumption(distance_m, avg_speed)
        
        efficiency = StatsCalculator.calculate_efficiency(work_area_m2, duration_seconds)
        
        coverage = 0.0
        if field_boundary and len(field_boundary) >= 3:
            coverage = StatsCalculator.calculate_field_coverage(
                gps_track, field_boundary, work_width
            )
        
        return {
            'distance_m': round(distance_m, 2),
            'distance_km': round(distance_km, 2),
            'work_area_m2': round(work_area_m2, 2),
            'work_area_mu': round(work_area_mu, 2),
            'fuel_consumption_l': round(fuel_l, 2),
            'efficiency_mu_per_hour': round(efficiency, 2),
            'coverage_percent': round(coverage, 2),
            'duration_hours': round(duration_seconds / 3600.0, 2)
        }

# 创建全局实例
calculator = StatsCalculator()

